#pragma once
#include <Windows.h>


LRESULT CALLBACK WinBaseProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);


class win_base
{
protected:
    win_base();
    ~win_base();

public:
	// You can override WinProc for each of your sub-class, 
	// but override the individual functions is more recommended.
	virtual LRESULT win_proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

public:
    virtual bool reg_class(HINSTANCE hInstance = NULL, PWCHAR pszClassName = NULL);
    virtual bool create(HWND hWndParent = NULL);
    virtual void destroy_window();
    virtual bool sub_class(HWND hWnd);

	void move_window(int x, int y, int width = -1, int height = -1, BOOL repaint = TRUE);
    void show_window(bool state = true);
    void redraw_window() { InvalidateRect(_hWnd, NULL, TRUE); }
    bool visible();
    bool minimized();
    bool maximized();

    HWND get_handle() { return _hWnd;}
    HWND get_parent() { return GetParent(_hWnd);}
    HINSTANCE get_instance() { return _hInstance;}
    LPCTSTR get_class_name() { return _szClassName; }
    LPCTSTR get_title() { return _szTitle; }
    DWORD get_style() { return _dwStyle; }
    INT get_x() { return _ptPos.x; }
    INT get_y() { return _ptPos.y; }
    INT get_width() { return _iWidth; }
    INT get_height() { return _iHeight; }
    INT screen_x() { return _ptScreenPos.x; }
    INT screen_y() { return _ptScreenPos.y; }


    void set_title(LPCWSTR szTitle);
    void set_style(DWORD dwStyle);
    void set_exstyle(DWORD dwExStyle);
    void set_parent(HWND hWnd) { _hParent = hWnd; }

protected:
	HWND		_hWnd;                          // The window handle
	HWND		_hParent;                       // The parent window handle
	HINSTANCE	_hInstance;                     // The window app instance

    WCHAR       _szClassName[256];              // The register class name
    WCHAR       _szTitle[256];                  // The title bar text
	DWORD		_dwStyle, _dwExStyle;           // The window style

    POINT       _ptPos;                         // The position of top-left conner
    POINT       _ptScreenPos;                   // The screen position of top-left conner
	INT			_iWidth;                        // The window width
	INT			_iHeight;                       // The window height


    WNDPROC     _oldProc;                      // Save the old GWL_WNDPROC
    LONG        _oldUserData;                  // Save the old GWL_USERDATA

    // Save the MSG, WPARAM and LPARAM in WndProc(), make them transparent to the message process functions
	UINT		_uMsg;
	WPARAM		_wParam;
	LPARAM		_lParam;

//Virtual base windows message process functions
public:
    inline LRESULT defProc()    { return _oldProc(_hWnd, _uMsg, _wParam, _lParam); }

	virtual LRESULT OnActivate(BOOL bActive, BOOL bClick, BOOL bMinimized, HWND hWndAgainst){ return defProc(); }
	virtual LRESULT OnActivateApp(BOOL bActive, DWORD dwThread)                             { return defProc(); }
	virtual LRESULT OnCancelMode()                                                          { return defProc(); }
	virtual LRESULT OnChar(DWORD dwKey, DWORD dwData)   		                            { return defProc(); }
	virtual LRESULT OnChildActivate()                                                       { return defProc(); }
	virtual LRESULT OnClose()                           		                            { return defProc(); }
	virtual LRESULT OnCommand(WORD wNotifyCode, WORD wCtrlID, HWND hWndCtrl)                { return defProc(); }
	virtual LRESULT OnDestroy()                                                     		{ return defProc(); }
	virtual LRESULT OnDrawItem(UINT uCtrlID, DRAWITEMSTRUCT * pDrawItemStruct)      		{ return defProc(); }
    virtual LRESULT OnEnable(BOOL bEnabled)	                                        		{ return defProc(); }
    virtual LRESULT OnEnterSizeMove()                                                       { return defProc(); }
	virtual LRESULT OnEraseBackground(HDC hDC)                                              { return defProc(); }
	virtual LRESULT OnExitSizeMove()                                                        { return defProc(); }
	virtual LRESULT OnGetMinMaxInfo(MINMAXINFO * pMMInfo)                                   { return defProc(); }
	virtual LRESULT OnHelp(HELPINFO * pHelpInfo)                                            { return defProc(); }
	virtual LRESULT OnHorScroll(int scrollCode, int pos, HWND scrollBar)                    { return defProc(); }
	virtual LRESULT OnKeyDown(DWORD dwKey, DWORD dwKeyData)                                 { return defProc(); }
    virtual LRESULT OnKeyUp(DWORD dwKey, DWORD dwKeyData)                                   { return defProc(); }
	virtual LRESULT OnKillFocus(HWND hWndReceiveFocus)                                      { return defProc(); }
	virtual LRESULT OnLeftDoubleClick(WORD x, WORD y, BOOL bCtrlDown, BOOL bShiftDown)      { return defProc(); }
	virtual LRESULT OnLeftDown(WORD x, WORD y, BOOL bCtrlDown, BOOL bShiftDown)             { return defProc(); }
	virtual LRESULT OnLeftUp(WORD x, WORD y, BOOL bCtrlDown, BOOL bShiftDown)               { return defProc(); }
	virtual LRESULT OnMouseActivate(HWND hWndTop, UINT uMouseMsg, INT iHitTest)             { return defProc(); }
	virtual LRESULT OnMouseMove(DWORD dwKeys, WORD x, WORD y)                               { return defProc(); }
	virtual LRESULT OnMouseWheel(WORD x, WORD y, WORD key, short distance)                  { return defProc(); }
    virtual LRESULT OnNcActivate(BOOL activating, HWND deactivatedWin)                      { return defProc(); }
	virtual LRESULT OnNcCalcSize(BOOL calcValidRects, LPARAM paramsOrRect)                  { return defProc(); }
	virtual LRESULT OnNcHitTest(WORD x, WORD y)                                             { return defProc(); }
	virtual LRESULT OnNcLeftDoubleClick(WORD x, WORD y, BOOL bCtrlDown, BOOL bShiftDown)    { return defProc(); }
	virtual LRESULT OnNcLeftDown(SHORT x, SHORT y, DWORD dwHitTestResult)                   { return defProc(); }
	virtual LRESULT OnNcLeftUp(SHORT x, SHORT y, DWORD dwHitTestResult)                     { return defProc(); }
	virtual LRESULT OnNcRightDown(SHORT x, SHORT y, DWORD dwHitTestResult)                  { return defProc(); }
	virtual LRESULT OnNcRightUp(SHORT x, SHORT y, DWORD dwHitTestResult)                    { return defProc(); }
	virtual LRESULT OnNotify(INT iCtrlId, NMHDR * pNotifyHdr)                               { return defProc(); }
	virtual LRESULT OnPaint()                                                               { return defProc(); }
	virtual LRESULT OnPaste()                                                               { return defProc(); }
    virtual LRESULT OnVerScroll(int scrollCode, int pos, HWND scrollBar)                    { return defProc(); }
	virtual LRESULT OnRightDoubleClick(WORD x, WORD y, BOOL bCtrlDown, BOOL bShiftDown)     { return defProc(); }
	virtual LRESULT OnRightDown(WORD x, WORD y, BOOL bCtrlDown, BOOL bShiftDown)            { return defProc(); }
	virtual LRESULT OnRightUp(WORD x, WORD y, BOOL bCtrlDown, BOOL bShiftDown)              { return defProc(); }
	virtual LRESULT OnSetCursor(HWND hWnd, WORD wHitTest, WORD wMouseMsg)                   { return defProc(); }
	virtual LRESULT OnSetFocus(HWND hWndLoseFocus)                                          { return defProc(); }
	virtual LRESULT OnSettingChange(DWORD wFlags, LPCTSTR pSection)                         { return defProc(); }
	virtual LRESULT OnShowWindow(BOOL bShown, int iStatus)                                  { return defProc(); }
	virtual LRESULT OnSize(DWORD dwFlags, WORD width, WORD height)                          { return defProc(); }
	virtual LRESULT OnSizing(DWORD edge, RECT * rect)                                       { return defProc(); }
	virtual LRESULT OnSysCommand(DWORD cmdType, WORD x, WORD y)                             { return defProc(); }
	virtual LRESULT OnTimer(DWORD dwTimerID, TIMERPROC* pTimeProc)                          { return defProc(); }
	virtual LRESULT OnWindowPosChanged(WINDOWPOS * pWndPos)                                 { return defProc(); }
	virtual LRESULT OnWindowPosChanging(WINDOWPOS * pWndPos)                                { return defProc(); }
};